﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MLopez.BizVal.CW.Base
{
    /// <summary>
    /// Encapsula una Etiqueta Lingüística triangular
    /// </summary>
    public class TriEtiqueta
    {
        /// <summary>
        /// Extremo inferior de la etiqueta
        /// </summary>
        public decimal A {get; set;}
        /// <summary>
        /// Valor modal de la etiqueta
        /// </summary>
        public decimal M {get; set;}
        /// <summary>
        /// Extremo superior de la etiqueta
        /// </summary>
        public decimal B {get; set;}

        /// <summary>
        /// Término en lenguaje natural que representa la etiqueta
        /// </summary>
        public String Termino
        {
            get;
            set;
        }

        public int Indice
        {
            get;
            set;
        }

        /// <summary>
        /// Crea una etiqueta triangular.
        /// </summary>
        /// <param name="a">Extremo inferior de la etiqueta</param>
        /// <param name="m">Valor Modal de la etiqueta</param>
        /// <param name="b">Extremo superior de la etiqueta</param>
        public TriEtiqueta(decimal a, decimal m, decimal b)
        {
            if ((a > m) || (a > b) || (m < a) || (m > b) || (b < a) || (b < m))
                throw new CWException(CWExceptionType.NoLabelSet);
            
            this.A = a;
            this.B = b;
            this.M = m;
        }

        /// <summary>
        /// Crea una nueva etiqueta triangular, asignandole un término en lenguaje natural.
        /// </summary>
        /// <param name="a">Extremo inferior de la etiqueta</param>
        /// <param name="m">Valor Modal de la etiqueta</param>
        /// <param name="b">Extremo superior de la etiqueta</param>
        /// <param name="termino">Término en lenguaje natural que representa la etiqueta.</param>
        public TriEtiqueta(decimal a, decimal m, decimal b, string termino):this(a,m,b)
        {
            Termino = termino;
        }
    

        /// <summary>
        /// Función de pertenencia triangular
        /// </summary>
        /// <param name="x">Valor real</param>
        /// <returns>Grado de pertenencia en [0,1]</returns>
        public decimal Pertenencia(decimal x)
        {
            decimal ret = 0;
            if (x <= A)
            {
                ret = 0;
            }
            else if ((x > A) && (x <= M))
            {
                ret = (x - A) / (M - A);
            }
            else if ((x > M) && (x < B))
            {
                ret = (B - x) / (B - M);
            }
            else if (x >= B)
            {
                ret = 0;
            }
            return ret;
        }

        /// <summary>
        /// Devuelve un valor indicando si una etiqueta es igual a la instancia.
        /// </summary>
        /// <param name="obj">Objeto a comparar</param>
        /// <returns>TRUE si <paramref name="obj"/> es una instancia de TriEtiqueta y su valor es el mismo. FALSE en otro caso</returns>
        public override bool Equals(object obj)
        {
            try
            {
                TriEtiqueta b = (TriEtiqueta)obj;
                return ((this.A == b.A) && (this.M == b.M) && (this.B == b.B));
            }
            catch
            {
                return false;
            }           
        }

        /// <summary>
        /// Convierte la instancia a una cadena de texto.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return String.Format("{0}({1:F4}, {2:F4}, {3:F4})", Termino, A, M, B);
        }

        /// <summary>
        /// Devuelve un código hash que representa la instancia.
        /// </summary>
        /// <returns>Código hash</returns>
        public override int GetHashCode()
        {
            string cadenaEtiqueta =  String.Format("({0}, {1}, {2})", A.ToString(), M.ToString(), B.ToString());
            return cadenaEtiqueta.GetHashCode();
        }
    }
}
